import HashHistory from "./component/hashHistory"
import View from './component/view'
import Link from './component/link'
let _Vue = null
console.log(_Vue)
class VueRouter {
    constructor(options) {

        this.options = options
        this.mode = options.mode || 'hash'
        switch (this.mode) {
            case 'hash':
                this.history = new HashHistory(this)
                break
            case 'history':

                break
            case 'abstract':
        }
    }
    init(app) {
        this.history.listen((route) => app._route = route)

        // 初始化时执行一次，保证刷新能渲染
        this.history.transitionTo(window.location.hash.slice(1))
    }

    // 根据hash变化获取对应的所有组件
    createMathcer(location) {
        const { pathMap } = createRouteMap(this.options.routes)

        const record = pathMap[location]
        const local = {
            path: location
        }
        if (record) {
            return createRoute(record, local)
        }
        return createRoute(null, local)
    }
}

VueRouter.install = (Vue) => {
    _Vue = Vue
    Vue.mixin({
        beforeCreate() {
            if (this.$options.router) { // 如果是根组件
                // this 是 根组件本身
                this._routerRoot = this

                // this.$options.router就是挂在根组件上的VueRouter实例
                this.$router = this.$options.router

                // 执行VueRouter实例上的init方法，初始化
                this.$router.init(this)

                // 相当于存在_routerRoot上，并且调用Vue的defineReactive方法进行响应式处理
                Vue.util.defineReactive(this, '_route', this.$router.history.current)
            } else {
                // 非根组件，也要把父组件的_routerRoot保存到自身身上
                this._routerRoot = this.$parent && this.$parent._routerRoot
                // 子组件也要挂上$router
                this.$router = this._routerRoot.$router
            }
        }
    })
    Object.defineProperty(Vue.prototype, '$route', {
        get() {
            return this._routerRoot._route
        }
    })
    Vue.component('RouterView', View)
    Vue.component('RouterLink', Link)
}

function createRouteMap(routes) {

    const pathList = []
    const pathMap = {}

    // 对传进来的routes数组进行遍历处理
    routes.forEach(route => {
        addRouteRecord(route, pathList, pathMap)
    })
    return {
        pathList,
        pathMap
    }
}

function addRouteRecord(route, pathList, pathMap, parent) {
    // 拼接path
    const path = parent ? `${parent.path}/${route.path}` : route.path
    const { component, children = null } = route
    const record = {
        path,
        component,
        parent
    }
    if (!pathMap[path]) {
        pathList.push(path)
        pathMap[path] = record
    }
    if (children) {
        // 如果有children，则递归执行addRouteRecord
        children.forEach(child => addRouteRecord(child, pathList, pathMap, record))
    }
}

function createRoute(record, location) {
    const res = []
    if (record) {
        while (record) {
            res.unshift(record)
            record = record.parent
        }
    }
    return {
        ...location,
        matched: res
    }
}
export default VueRouter

